/*
 * configure_adc.c
 *
 *  Created on: 2021��5��27��
 *      Author: Administrator
 */

#include "spi_driver.h"
#include "xil_printf.h"
#include "../gpio/gwGpio.h"
#include "../utility.h"
#include "../hwicap/hwicap.h"

static TaskHandle_t xSpiConfigureTask;

u32 lmx2594_4g_7_8125m[] = {
0x006416,
0x006414,
0x700000,
0x6F0000,
0x6E0000,
0x6D0000,
0x6C0000,
0x6B0000,
0x6A0000,
0x690001,
0x680000,
0x670000,
0x660000,
0x650011,
0x640000,
0x630000,
0x620000,
0x610888,
0x600000,
0x5F0000,
0x5E0000,
0x5D0000,
0x5C0000,
0x5B0000,
0x5A0000,
0x590000,
0x580000,
0x570000,
0x560000,
0x550000,
0x540000,
0x530000,
0x520000,
0x510000,
0x500000,
0x4F0000,
0x4E0003,
0x4D0000,
0x4C000C,
0x4B0800,
0x4AF000,
0x49003F,
0x48000E,
0x470089,
0x46C350,
0x450000,
0x4403E8,
0x430000,
0x4201F4,
0x410000,
0x401388,
0x3F0000,
0x3E0322,
0x3D00A8,
0x3C0000,
0x3B0001,
0x3A2001,
0x390020,
0x380000,
0x370000,
0x360000,
0x350000,
0x340820,
0x330080,
0x320000,
0x314180,
0x300300,
0x2F0300,
0x2E07FE,
0x2DC0DF,
0x2C1F23,
0x2B0000,
0x2A0000,
0x290000,
0x280000,
0x2703E8,
0x260000,
0x250304,
0x240028,
0x230004,
0x220000,
0x211E21,
0x200393,
0x1F43EC,
0x1E318C,
0x1D318C,
0x1C0488,
0x1B0002,
0x1A0DB0,
0x190C2B,
0x18071A,
0x17007C,
0x160001,
0x150401,
0x14E048,
0x1327B7,
0x120064,
0x11012C,
0x100080,
0x0F064F,
0x0E1E50,
0x0D4000,
0x0C5002,
0x0B0018,
0x0A10D8,
0x090604,
0x082000,
0x0740B2,
0x06C802,
0x0500C8,
0x040A43,
0x030642,
0x020500,
0x010808,
0x00641C,
0x00641C
};

u32 lmx_6G[] = {
0x002716,
0x002714,
0x700000,
0x6F0000,
0x6E0000,
0x6D0000,
0x6C0000,
0x6B0000,
0x6A0000,
0x690001,
0x680000,
0x670000,
0x660000,
0x650011,
0x640000,
0x630000,
0x620000,
0x610888,
0x600000,
0x5F0000,
0x5E0000,
0x5D0000,
0x5C0000,
0x5B0000,
0x5A0000,
0x590000,
0x580000,
0x570000,
0x560000,
0x550000,
0x540000,
0x530000,
0x520000,
0x510000,
0x500000,
0x4F0000,
0x4E0003,
0x4D0000,
0x4C000C,
0x4B0800,
0x4AF000,
0x49003F,
0x480016,
0x470081,
0x46C350,
0x450000,
0x4403E8,
0x430000,
0x4201F4,
0x410000,
0x401388,
0x3F0000,
0x3E0322,
0x3D00A8,
0x3C0000,
0x3B0001,
0x3A2001,
0x390020,
0x380000,
0x370000,
0x360000,
0x350000,
0x340820,
0x330080,
0x320000,
0x314180,
0x300300,
0x2F0300,
0x2E07FE,
0x2DC0DF,
0x2C1F23,
0x2B0000,
0x2A0000,
0x290000,
0x280000,
0x2703E8,
0x260000,
0x250404,
0x24003C,
0x230004,
0x220000,
0x211E21,
0x200393,
0x1F03EC,
0x1E318C,
0x1D318C,
0x1C0488,
0x1B0002,
0x1A0DB0,
0x190C2B,
0x18071A,
0x17007C,
0x160001,
0x150401,
0x14E048,
0x1327B7,
0x120064,
0x11012C,
0x100080,
0x0F064F,
0x0E1E30,
0x0D4000,
0x0C5001,
0x0B0018,
0x0A10D8,
0x091604,
0x082000,
0x0700B2,
0x06C802,
0x0500C8,
0x040A43,
0x030642,
0x020500,
0x010808,
0x00271C,
0x00271C                             
};

u32 hmc7044_config1_data[] = {
0x000001,
0x000000,
0x009600,
0x009700,
0x009800,
0x009900,
0x009a00,
0x009baa,
0x009caa,
0x009daa,
0x009eaa,
0x009f4d,
0x00a0df,
0x00a197,
0x00a203,
0x00a300,
0x00a400,
0x00a506,
0x00a61c,
0x00a700,
0x00a806,
0x00a900,
0x00ab00,
0x00ac20,
0x00ad00,
0x00ae08,
0x00af50,
0x00b004,
0x00b10d,
0x00b200,
0x00b300,
0x00b400,
0x00b500,
0x00b600,
0x00b700,
0x00b800,
0x000160,
0x000240,
0x00032f,
0x00047c,
0x000544,
0x000600,
0x000700,
0x000800,
0x000901,
0x004610,
0x004710,
0x004800,
0x004912,
0x005029,
0x005131,
0x005202,
0x005300,
0x005401,
0x003101,
0x003201,
0x003301,
0x003400,
0x00351e,
0x003600,
0x00370f,
0x003818,
0x003900,
0x003a00,
0x003b00,
0x000a00,
0x000b00,
0x000c07,
0x000d00,
0x000e07,
0x0014aa,
0x001501,
0x00160c,
0x001734,
0x00180c,
0x001902,
0x001a08,
0x001b18,
0x001c01,
0x001d01,
0x001e01,
0x001f01,
0x00200a,
0x00210a,
0x002200,
0x0026c8,
0x002700,
0x002814,
0x002907,
0x002a00,
0x005a00,
0x005b02,
0x005c00,
0x005d03,
0x006400,
0x006500,
0x0070ff,
0x00711f,
0x00c8f2,
0x00c901,
0x00ca00,
0x00cb00,
0x00cc02,
0x00cd00,
0x00ce00,
0x00cf00,
0x00d008,
0x00d100,
0x00d27C,
0x00d300,
0x00d402,
0x00d505,
0x00d602,
0x00d700,
0x00d800,
0x00d901,
0x00daa8,
0x00db00,
0x00dcf2,
0x00dd01,
0x00de00,
0x00df00,
0x00e004,
0x00e100,
0x00e200,
0x00e300,
0x00e408,
0x00e500,
0x00e67c,
0x00e700,
0x00e802,
0x00e903,
0x00ea03,
0x00eb00,
0x00ec00,
0x00ed01,
0x00eea8,
0x00ef00,
0x00f0f3,
0x00f10c,
0x00f200,
0x00f300,
0x00f400,
0x00f500,
0x00f600,
0x00f700,
0x00f803,
0x00f900,
0x00fa7C,
0x00fb00,
0x00fc02,
0x00fd06,
0x00fe02,
0x00ff00,
0x010000,
0x010101,
0x0102a8,
0x010300,
0x0104f2,
0x01050c,
0x010600,
0x010700,
0x010800,
0x010900,
0x010a00,
0x010b00,
0x010c03,
0x010d00,
0x010ef3,
0x010f18,
0x011000,
0x011100,
0x011200,
0x011300,
0x011400,
0x011500,
0x011610,
0x011700,
0x0118f3,
0x01190c,
0x011a00,
0x011b00,
0x011c00,
0x011d00,
0x011e00,
0x011f00,
0x012010,
0x012100,
0x01227c,
0x012300,
0x012402,
0x012503,
0x012602,
0x012700,
0x012800,
0x012901,
0x012ab0,
0x012b00,
0x012cf3,
0x012d0c,
0x012e00,
0x012f00,
0x013000,
0x013100,
0x013200,
0x013300,
0x013410,
0x013500,
0x01367d,
0x013780,
0x013801,
0x013900,
0x013a00,
0x013b00,
0x013c00,
0x013d01,
0x013eb0,
0x013f00,
0x0140f3,
0x014118,
0x014200,
0x014300,
0x014400,
0x014500,
0x014600,
0x014700,
0x014810,
0x014900,
0x014af2,
0x014b0c,
0x014c00,
0x014d00,
0x014e01,
0x014f00,
0x015000,
0x015100,
0x015210,
0x015300
};

u32 hmc7044_config2_data[] = {
0x000162,
0x000160
};

u32 hmc7044_config3_data[] = {
0x0001e0,
0x000160
};

u32 hmc7044_config4_data[] = {
0x000164	
};

u32 hmc7044_config5_data[] = {
0x000160	
};

u32 hmc7044_pll1_pll2Det_data[] = {
0x005035	
};

u32 hmc7044_pll2Det_data[] = {
0x005029	
};

u32 adc_data[] = {
0x0000BC,
0x0201fe,
0x004004,
0x020022,
0x0202c0,
0x020c01,
0x020d00,
0x021066,
0x021166,
0x021266,
0x021326,
0x021600,
0x003280,
0x005184,
0x005802,
0x006603,
0x00500e,
0x0201ff,
0x0030f0,
0x0030c0,
0x002200,
0x002300
};

u32 dac_data[] = {
0x000001,
0x00d252,
0x00d2d2,
0x060602,
0x060700,
0x060401,
0x860400,
0x005803,
0x00901e,
0x008000,
0x003fc6,
0x004000,
0x004103,
0x00429f,
0x00200f,
0x009e85,
0x0091e9,
0x809200,
0x00e820,
0x015200,
0x030000,
0x04b8ff,
0x04b901,
0x048038,
0x048138,
0x048238,
0x048338,
0x048438,
0x048538,
0x048638,
0x048738,
0x011044,
0x0111c3,
0x023028,
0x028900,
0x008400,
0x020000,
0x047509,
0x045383,
0x04582f,
0x045920,
0x045d00,
0x047501,
0x02010f,
0x02a701,
0x02ae01,
0x029e1f,
0x020600,
0x020601,
0x003904,
0x030837,
0x030925,
0x030a13,
0x030b01,
0x028003,
0x828100,
0x030001,
0x00241f,
0x04baff,
0x04bb01,
0x011145,
0x015000,
0x011300,
0x011991,
0x011811,
0x011711,
0x011611,
0x011511,
0x011411,
0x011301,
0x047509,
0x047501,
0x847000,
0x847100,
0x847200,
0x847300
};

void zeros_buf(u8 *buf, int length){
	int i=0;
	for(i=0;i<length;i++){
		*(buf+i) = 0;
	}
}

void set_buf(u8 *buf, int length, u32 val){
	zeros_buf(buf,length);
	int i;
	u32 mask_0 = 0xff;
	for(i=0;i<length;i++){
		u32 mask = mask_0 << (i*8);
		u32 data = (val & mask);
		data = data >> (i*8);
		buf[length-1-i] = (u8)(data);
	}
}

u8 spi_read(u32 base_addr, u32 data, u32 slave_mask){
	gw_sleep(DELAY_WR);
	u8 wb[3] = { 0,0,0}; //{cmd,addr,data}
	u8 rb[3] = { 0,0,0};

	set_buf(wb,3,data);
	int status = xSpi_trans(slave_mask, wb, rb, 3);
	if(status != 0){
		xil_printf(" !!!!! Spi read error : status = %d \r\n", status);
		return -1;
	}
	// spi_trans(base_addr, slave_mask, wb, rb, 3, 0);
	xil_printf("Spi read : wb -- 0x%02x%02x%02x, rb -- 0x%02x%02x%02x \r\n", wb[0],wb[1],wb[2],rb[0],rb[1],rb[2]);
	return rb[2];
}

void spi_write(u32 base_addr, u32 data, u32 slave_mask){
	gw_sleep(DELAY_WR);
	u8 wb[3] = { 0,0,0}; //{cmd(1bit),addr(7bit),data(16bit)}
	u8 rb[3] = { 0,0,0};
	set_buf(wb,3,data);
	int status = xSpi_trans(slave_mask, wb, rb, 3);
	if(status != 0){
		xil_printf(" !!!!! Spi write error : status = %d \r\n", status);
		return;
	}
	// spi_trans(base_addr, slave_mask, wb, rb, 3, 0);
	// xil_printf(" --------- Spi write : wb -- 0x%02x%02x%02x, rb -- 0x%02x%02x%02x \r\n", wb[0],wb[1],wb[2],rb[0],rb[1],rb[2]);
}

int adc_clock(){
	int i,len;
	len = sizeof(lmx2594_4g_7_8125m) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, lmx2594_4g_7_8125m[i], LMX_ADC_SS);
	}
	xil_printf("wait adc_clock ..... \r\n");
	return 0;
}

int dac_clock(){
	int i,len;
	len = sizeof(lmx_6G) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, lmx_6G[i], LMX_DAC_SS);
	}

	xil_printf("wait dac_clock ..... \r\n");
	return 0;
}

int hmc7044_config1(){
	int i,len;
	len = sizeof(hmc7044_config1_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_config1_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_config1 ..... \r\n");
	return 0;
}

int hmc7044_config2(){
	int i,len;
	len = sizeof(hmc7044_config2_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_config2_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_config2 ..... \r\n");
	return 0;
}

int hmc7044_config3(){
	int i,len;
	len = sizeof(hmc7044_config3_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_config3_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_config3 ..... \r\n");
	return 0;
}

int hmc7044_config4(){
	int i,len;
	len = sizeof(hmc7044_config4_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_config4_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_config4 ..... \r\n");
	return 0;
}

int hmc7044_config5(){
	int i,len;
	len = sizeof(hmc7044_config5_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_config5_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_config5 ..... \r\n");
	return 0;
}

int hmc7044_pll1_pll2Det(){
	int i,len;
	len = sizeof(hmc7044_pll1_pll2Det_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_pll1_pll2Det_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_pll1_pll2Det ..... \r\n");
	return 0;
}

int hmc7044_pll2Det(){
	int i,len;
	len = sizeof(hmc7044_pll2Det_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, hmc7044_pll2Det_data[i], HMC7044_SPI_SS);
	}
	xil_printf("wait hmc7044_pll2Det ..... \r\n");
	return 0;
}

/* 3 wire to 4 wire configure */
int adc_config(){
	int i,len;
	len = sizeof(adc_data) / sizeof(u32);

	for(i=0;i<len;i++){
		spi_write(XPAR_AXI_SPI_BASEADDR, adc_data[i], ADC_SPI_SS);
	}

	xil_printf("wait adc_config ..... \r\n");

	return 0;
}

int dac_config(){
	int i,len;
	len = sizeof(dac_data) / sizeof(u32);

	for(i=0;i<len;i++){
		if(dac_data[i] == 0x860400){
			spi_write(XPAR_AXI_SPI_BASEADDR, 0x060400, DAC_SPI_SS);
			spi_write(XPAR_AXI_SPI_BASEADDR, 0x060401, DAC_SPI_SS);

			u8 rx_data = spi_read(XPAR_AXI_SPI_BASEADDR, 0x860400, DAC_SPI_SS);
			u8 data = (rx_data & 0x2);
			if(data != 0x2){
				return -1;
			}
		}else if(dac_data[i] == 0x809200){
			u8 rx_data = spi_read(XPAR_AXI_SPI_BASEADDR, 0x809200, DAC_SPI_SS);
			u8 data = (rx_data & 0x1);
			if(data != 1){
				return -1;
			}
		}else if(dac_data[i] == 0x828100){
			u8 rx_data = spi_read(XPAR_AXI_SPI_BASEADDR, 0x828100, DAC_SPI_SS);
			u8 data = (rx_data & 0x1);
			if(data != 1){
				return -1;
			}
		}
		spi_write(XPAR_AXI_SPI_BASEADDR, dac_data[i], DAC_SPI_SS);
	}

	xil_printf("wait dac_config ..... \r\n");

	return 0;
}

int dac_read(){
	int i,len;
	len = sizeof(dac_data) / sizeof(u32);

	for(i=0;i<len;i++){
		u32 data = dac_data[i];
		data = data & 0xffff00;
		if(data < 0x800000){
			data = data + 0x800000;
		}
		spi_read(XPAR_AXI_SPI_BASEADDR, data, DAC_SPI_SS);
	}

	xil_printf("read dac ..... \r\n");

	return 0;
}

void reset_204B(){
    set_gpio(O_SOFT_RST);
	gw_sleep(DELAY_CNT);
    reset_gpio(O_SOFT_RST);
}

int spi_configure(){

	xil_printf(" \r\n ****** start spi_configure ****** \r\n");

	spi_read(XPAR_AXI_SPI_BASEADDR,0x80c800, HMC7044_SPI_SS);
	spi_read(XPAR_AXI_SPI_BASEADDR,0x807d00, HMC7044_SPI_SS);

	u8 freq_7044 = spi_read(XPAR_AXI_SPI_BASEADDR,0x810500, HMC7044_SPI_SS);

	if( freq_7044 != 0x0c | !(read_gpio(I_HMC7044_LOCKED))){
		gpio_startup();

		adc_clock();
		dac_clock();

		hmc7044_config1();
		hmc7044_config2();

		/* check sfp_link gpio */
		if(read_gpio(I_SFP_LINKSTATE) == 1){
			hmc7044_pll1_pll2Det();
		}else{
			hmc7044_pll2Det();
		}

		/* check 3 gpio */
		if( !(read_gpio(I_HMC7044_LOCKED)) ){
			return -1;
		}
		
		hmc7044_config3();

		/* check 1 gpio */
		if( !read_gpio(I_HMC7044_PHASE)){
			return -1;
		}

		xil_printf("I_HMC7044_LOCKED : %d, I_HMC7044_PHASE : %d \r\n", read_gpio(I_HMC7044_LOCKED) , read_gpio(I_HMC7044_PHASE));
		spi_read(XPAR_AXI_SPI_BASEADDR,0x810500, HMC7044_SPI_SS);

		/* send gpio signal to fpga */
		set_gpio(O_SYNC_TO_PL); // via register ? -- 20210611

		xil_printf("----------------- reconfigure fpga bit ----------------- r\n");

		gw_sleep(1000);

		HwIcaptest();
	}

	xil_printf("normal process .................\r\n");

	adc_config();

	while(dac_config() == -1){
		gw_sleep(DELAY_CNT);
		// post event to eventHandler();
	}

	hmc7044_config4();
	set_gpio(O_LMX_ADC_SYSREFREQ);
	set_gpio(O_LMX_DAC_SYSREFREQ);

	/* reset 204B IP via gpio */
	reset_204B();

	gw_sleep(DELAY_CNT);
	// hmc7044_config5();
	// reset_gpio(O_LMX_ADC_SYSREFREQ);
	// reset_gpio(O_LMX_DAC_SYSREFREQ);


	spi_read(XPAR_AXI_SPI_BASEADDR, 0x847000, DAC_SPI_SS);
	spi_read(XPAR_AXI_SPI_BASEADDR, 0x847100, DAC_SPI_SS);
	spi_read(XPAR_AXI_SPI_BASEADDR, 0x847200, DAC_SPI_SS);
	spi_read(XPAR_AXI_SPI_BASEADDR, 0x847300, DAC_SPI_SS);
	xil_printf("tx sync : %d, rx sync : %d \r\n",  read_gpio(I_TX_SYNC),  read_gpio(I_RX_SYNC));

	u8 rx_data = spi_read(XPAR_AXI_SPI_BASEADDR, 0x847300, DAC_SPI_SS);
	if(rx_data != 0xf){
		return -1;
	}

	if( (read_gpio(I_RX_SYNC) != 1)){
		return -1;
	}

	if( (read_gpio(I_TX_SYNC) != 1)){
		return -1;
	}

	spi_write(XPAR_AXI_SPI_BASEADDR, 0x0104f3, HMC7044_SPI_SS);
	
	// dac_read();

	return 0;
}


static void spiConfigureTask( void *pvParameters )
{
	QueueHandle_t xEventQueue = (QueueHandle_t)pvParameters;

	for( ;; )
	{
		if(spi_configure() == 0){
			break;
		}
	}

    Event event;
    makeEvent(&event, 2, EVENT_CONFIGURE_OK, NULL);
    xQueueSend( xEventQueue, &event, 0UL );

	vTaskDelete( xSpiConfigureTask );
}

int createSpiConfigureTask(QueueHandle_t xEventQueue){
    BaseType_t xReturn = xTaskCreate( spiConfigureTask, 
	                                  (const char *) "spiConfigureTask", 
									  configMINIMAL_STACK_SIZE * 2, 
									  xEventQueue, 
									  tskIDLE_PRIORITY + 3, /* gw_priority */
									  &xSpiConfigureTask);
	if(xReturn != pdPASS){
		return -1;
	}
	return 0;
}


/*************************** cli ****************************/
int cli_spi_read(u32 data, u32 slave_mask, u8 *rx_data){
	u8 wb[3] = { 0,0,0}; //{cmd,addr,data}
	u8 rb[3] = { 0,0,0};

	set_buf(wb,3,data);
	int status = xSpi_trans(slave_mask, wb, rb, 3);
	if(status != 0){
		// xil_printf(" !!!!! Spi read error : status = %d \r\n", status);
		return -1;
	}
	*rx_data = rb[2];
	return 0;
}

int cli_spi_write(u32 data, u32 slave_mask){
	u8 wb[3] = { 0,0,0}; //{cmd(1bit),addr(7bit),data(16bit)}
	u8 rb[3] = { 0,0,0};
	set_buf(wb,3,data);
	int status = xSpi_trans(slave_mask, wb, rb, 3);
	if(status != 0){
		return -1;
	}
	return 0;
}

int monitor_204b(){
	u8 rx_data = spi_read(XPAR_AXI_SPI_BASEADDR, 0x847300, DAC_SPI_SS);
	if(rx_data != 0xf){
		return -1;
	}
	if( (read_gpio(I_RX_SYNC) != 1)){
		return -1;
	}
	if( (read_gpio(I_TX_SYNC) != 1)){
		return -1;
	}
	return 0;
}

